package v1

import (
	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/jinzhu/gorm"
	"github.com/unknwon/com"
	"net/http"
	"repairs/models"
	"repairs/pkg/app"
	"repairs/pkg/e"
	"repairs/pkg/setting"
	"repairs/pkg/util"
	"repairs/service/rent_service"
	"repairs/service/user_service"
)

type GetUserRentJSON struct {
	UserID int `json:"user_id" valid:"Required;Min(1)"`
}

// @Summary 获取用户租借信息
// @Accept json
// @Tags 租借
// @Produce json
// @Param user_id body int true "用户id"
// @Success 200 {object} app.Response
// @Failure 500 {object} app.Response
// @Router /api/v1/user_rent [get]
func GetUserRent(c *gin.Context) {
	var (
		appG              = app.Gin{C: c}
		valid             = validation.Validation{}
		data              = models.RentRecord{}
		r                 GetUserRentJSON
		httpCode, errCode = http.StatusOK, e.SUCCESS
	)
	data.ID = -1
	for true {
		if err := c.ShouldBindWith(&r, binding.JSON); err != nil {
			app.MarkErrors(valid.Errors)
			httpCode, errCode = http.StatusBadRequest, e.InvalidParams
			break
		}
		if ok, _ := valid.Valid(&r); !ok {
			app.MarkErrors(valid.Errors)
			httpCode, errCode = http.StatusBadRequest, e.InvalidParams
			break
		}

		rentService := rent_service.RentRecord{
			UserID: r.UserID,
		}

		rent, err := rentService.GetUserRent()
		if err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorGetUserRentFail
			if err == gorm.ErrRecordNotFound {
				httpCode, errCode = http.StatusOK, e.ErrorNotExistRentFail
			}
			break
		}
		data = rent
		break
	}
	appG.Response(httpCode, errCode, data)
}

type AddRentJSON struct {
	UserID    int    `json:"user_id" valid:"Required;"`
	Room      string `json:"room" valid:"Required;MaxSize(20)"`
	StartTime int64  `json:"start_time" valid:"Required;Min(1606383053)"`
	EndTime   int64  `json:"end_time" valid:"Required;Min(1606383053)"`
}

// @Summary 添加租借记录
// @Accept json
// @Tags 租借
// @Produce json
// @Param user_id body int true "用户id"
// @Param room body string ture "房间"
// @Param start_time body int64 true "开始时间戳"
// @Param end_time body int64 true "结束时间戳"
// @Success 200 {object} app.Response
// @Success 500 {object} app.Response
// @Router /api/v1/rents [post]
// 检查租借是否合法, 并返回租借的凭证
func AddRent(c *gin.Context) {
	var (
		appG = app.Gin{C: c}
		json AddRentJSON
		data string
	)
	httpCode, errCode := app.BindAndValid(c, &json)
	for true {
		if errCode != e.SUCCESS {
			break
		}

		rentService := rent_service.RentRecord{
			UserID:    json.UserID,
			Room:      json.Room,
			StartTime: json.StartTime,
			EndTime:   json.EndTime,
		}
		exist, err := rentService.ExistByRoom()
		if err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorSystemDataBaseFail
			break
		}
		if exist {
			httpCode, errCode = http.StatusBadRequest, e.ErrorRentExistFail
			break
		}
		userService := user_service.User{ID: json.UserID}
		if err := userService.GetUser(); err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorGetUserFail
			break
		}
		data = util.GenerateRentKey(userService.Username)

		if err := rentService.Add(data); err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorAddUserFail
			break
		}
		break
	}
	appG.Response(httpCode, errCode, data)
}

// @Summary 删除租借记录
// @Accept json
// @Tags 租借
// @Param id path int true "租借id"
// @Success 200 {object} app.Response
// @Success 500 {object} app.Response
// @Router /api/v1/rents/{id} [delete]
func DeleteRent(c *gin.Context) {
	var (
		appG              = app.Gin{C: c}
		valid             = validation.Validation{}
		id                = com.StrTo(c.Param("id")).MustInt()
		httpCode, errCode = http.StatusOK, e.SUCCESS
	)
	valid.Min(id, 1, "id").Message("ID必须大于0")
	for true {
		if valid.HasErrors() {
			app.MarkErrors(valid.Errors)
			httpCode, errCode = http.StatusOK, e.InvalidParams
			break
		}

		rentService := rent_service.RentRecord{ID: id}

		exists, err := rentService.ExistById()
		if err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ERROR
			break
		}
		if !exists {
			httpCode, errCode = http.StatusOK, e.ErrorNotExistRentFail
			break
		}
		err = rentService.Delete()

		if err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorDeleteRentFail
			break
		}
		break
	}
	appG.Response(httpCode, errCode, nil)
}

type GetRentJSON struct {
	Room       string   `json:"room"`
	StartRange [2]int64 `json:"start_range"`
	EndRange   [2]int64 `json:"end_range"`
	PageNum    int      `json:"page_num" valid:"Required"`
}

// @Summary 获取租借列表
// @Accept json
// @Tags 租借
// @Produce json
// @Param Room body string false "租借的房间"
// @Param start_range body array false "开始时间的区间"
// @Param end_range body array false "结束时间的区间"
// @Param page_num body int true "页号"
// @Success 200 {object} app.Response
// @Success 500 {object} app.Response
// @Router /api/v1/rents [get]
func GetRents(c *gin.Context) {
	var (
		appG = app.Gin{C: c}
		data map[string]interface{}
		json GetRentJSON
	)
	httpCode, errCode := app.BindAndValid(c, &json)

	for true {
		if errCode != e.SUCCESS {
			break
		}
		rentService := rent_service.RentRecord{
			PageNum:    util.GetPageByNum(json.PageNum),
			PageSize:   setting.AppSetting.PageSize,
			StartRange: json.StartRange,
			EndRange:   json.EndRange,
			Room:       json.Room,
		}
		total, err := rentService.Count()
		if err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorCountRentFail
			break
		}

		rents, err := rentService.GetAll()
		if err != nil {
			httpCode, errCode = http.StatusInternalServerError, e.ErrorGetRentFail
			break
		}
		data = make(map[string]interface{})
		data["lists"] = rents
		data["total"] = total
		break
	}
	appG.Response(httpCode, errCode, data)
}
